﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using Space.Library.Data;
using Space.Model;
using Space.Model.Data;
using Space.Model.Entity;

namespace Space.Library
{
    // Depends on board.
    public class Painter
    {
        private static Graphics _paintGraphics;
        private static Bitmap _internalDrawBitmap;
        private static Graphics _g;

        private Dictionary<string, ImageResource> _imageList = new Dictionary<string, ImageResource>(StringComparer.InvariantCultureIgnoreCase);
        private ShipPainter _shipPainter;

        public Painter(Graphics graphicsIn)
        {
            _paintGraphics = graphicsIn;
        }

        public void Init()
        {
            _shipPainter = new ShipPainter(this);
            _internalDrawBitmap = new Bitmap(Board.Width, Board.Height);
            _g = Graphics.FromImage(_internalDrawBitmap);
        }

        public void Paint(GameRunner runner)
        {
            _g.Clear(Color.Black);

            foreach (var target in runner.Entities.OfType<IPaint>())
            {
                target.Paint(this, runner);
            }

            _paintGraphics.DrawImage(_internalDrawBitmap, 0, 0);
        }

        /*********************************************************
         * Data management 
        */

        public void LoadModel(ImageResource resource)
        {
            resource.Image = Image.FromFile(resource.Path);

            _imageList.Add(resource.Name, resource);
        }

        /*********************************************************
         * Translation
         */

        /*********************************************************
         * Graphical functions 
         */
        public void PutPixel(float x, float y, SolidBrush brush)
        {
            _g.FillRectangle(brush, x, y, 1, 1);
        }

        public void PutPixel(PointF pos, SolidBrush brush)
        {
            _g.FillRectangle(brush, pos.X, pos.Y, 1, 1);
        }



        public void DrawShip(Ship ship)
        {
            var shipImage = _shipPainter.CreateShipBitmap(ship);

            var transPos = ship.Pos - Board.SsizeHalf;

            // Flip Y-axis
            var y = FlipYAxis(transPos.Y);


            // Translate and rotate around center
            SetRotation(ship.Orientation, transPos.X + Board.SsizeHalf, y + Board.SsizeHalf);
            _g.TranslateTransform(transPos.X, y);

            // Draw to screen
            _g.DrawImage(shipImage, 0, 0, Board.Ssize, Board.Ssize);

            _g.ResetTransform();

            // Draw selected data.
            _g.TranslateTransform(transPos.X, y);
            if (ship.IsSelected)
            {
                // Selected rectangle
                _g.DrawRectangle(Pens.DodgerBlue, 0, 0, Board.Ssize, Board.Ssize);

                // Weapon range
                _g.TranslateTransform(Board.SsizeHalf, Board.SsizeHalf);
                var halfMaxRange = Board.SsizeHalf * ship.ShipModel.Weapons.Max(weapon => weapon.Range);
                _g.DrawArc(Pens.Red, -halfMaxRange, -halfMaxRange, 2 * halfMaxRange, 2 * halfMaxRange, 0, 360);
            }
            _g.ResetTransform();
        }

        private static float FlipYAxis(float y)
        {
            return (Board.BoardYMax) * Board.Ssize - y;
        }

        public Image GetShipModel(ShipModel model)
        {
            return _imageList[GetModelName(model)].Image;
        }

        private string GetModelName(ShipModel shipModel)
        {
            return ((int)shipModel.Owner).ToString() + "_" + shipModel.ShipType.ToString();
        }

        public void SetRotation(float rotationAngle, float x, float y)
        {
            var a = new Matrix();
            a.RotateAt(rotationAngle, new PointF(x, y));
            _g.Transform = a;
        }

        public void ResetTransform()
        {
            _g.ResetTransform();
        }

        public void PutText(string text, Font font, float x, float y, float w, float h, Color c)
        {
            _g.FillRectangle(Brushes.Black, new Rectangle((int)x, (int)y, (int)w, (int)h));

            _g.DrawString(text, font, new SolidBrush(c), new RectangleF(x, y, w, h));
        }

        public void Reset()
        {
            _g.Clear(Color.Black);
        }

        public void DrawLine(float x, float y, float x2, float y2, Color color, float width)
        {
            _g.DrawLine(new Pen(color, width), x, FlipYAxis(y), x2, FlipYAxis(y2));
        }

        public Image GetEngineImage(string type)
        {
            return _imageList[type].Image;
        }
    }
}
